﻿using Sidvall.IdentityManager.UI.Messaging;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Sidvall.IdentityManager.UI
{
    public partial class SystemContext
    {
        #region Public Members

        public const int MaxViewPluginCount = 5;

        #region ActiveServerItem

        public Sidvall.IdentityManager.UI.Entities.ServerItem ActiveServerItem
        {
            get
            {
                if (this.UserConfiguration == null)
                    return null;
                return (from o in this.UserConfiguration.ServerItems
                        where o.ServerItemId == Sidvall.IdentityManager.SystemContext.Current.ActiveServerItemId
                        select o).FirstOrDefault();
            }
        }

        #endregion
        #region UserConfiguration

        private Sidvall.IdentityManager.UI.Entities.UserConfiguration _UserConfiguration;
        public Sidvall.IdentityManager.UI.Entities.UserConfiguration UserConfiguration
        {
            get
            {
                return _UserConfiguration;
            }
            private set
            {
                _UserConfiguration = Sidvall.IdentityManager.UI.SystemContextConfig.Current.EntityFacade.UserConfigurationManager.GetValidConfiguration(value);
            }
        }

        #endregion
        #region ValidEditViewPlugins

        private List<Sidvall.IdentityManager.UI.Entities.Plugin> _ValidEditViewPlugins;
        public List<Sidvall.IdentityManager.UI.Entities.Plugin> ValidEditViewPlugins
        {
            get
            {
                return _ValidEditViewPlugins;
            }
            private set
            {
                _ValidEditViewPlugins = value;
            }
        }

        #endregion
        #region ValidFilterPlugins

        private List<Sidvall.IdentityManager.UI.Entities.Plugin> _ValidFilterPlugins;
        public List<Sidvall.IdentityManager.UI.Entities.Plugin> ValidFilterPlugins
        {
            get
            {
                return _ValidFilterPlugins;
            }
            private set
            {
                _ValidFilterPlugins = value;
            }
        }

        #endregion
        #region ValidFilterViewPlugins

        private List<Sidvall.IdentityManager.UI.Entities.Plugin> _ValidFilterViewPlugins;
        public List<Sidvall.IdentityManager.UI.Entities.Plugin> ValidFilterViewPlugins
        {
            get
            {
                return _ValidFilterViewPlugins;
            }
            private set
            {
                _ValidFilterViewPlugins = value;
            }
        }

        #endregion
        #region EditViewPluginCount

        public int EditViewPluginCount
        {
            get
            {
                int count;

                if (this.ValidEditViewPlugins == null)
                    return 0;
                count = this.ValidEditViewPlugins.Count;
                if (count > MaxViewPluginCount)
                    count = MaxViewPluginCount;
                return count;
            }
        }

        #endregion
        #region FilterViewPluginCount

        public int FilterViewPluginCount
        {
            get
            {
                int count;

                if (this.ValidFilterViewPlugins == null)
                    return 0;
                count = this.ValidFilterViewPlugins.Count;
                if (count > MaxViewPluginCount)
                    count = MaxViewPluginCount;
                return count;
            }
        }

        #endregion

        #region GetEditViewPlugin

        public Sidvall.IdentityManager.UI.Entities.Plugin GetEditViewPlugin(int index)
        {
            if (this.ValidEditViewPlugins == null)
                return this.MissingPlugin;
            if (this.ValidEditViewPlugins.Count < index + 1)
                return this.MissingPlugin;
            return this.ValidEditViewPlugins[index];
        }

        #endregion
        #region GetFilterViewPlugin

        public Sidvall.IdentityManager.UI.Entities.Plugin GetFilterViewPlugin(int index)
        {
            if (this.ValidFilterViewPlugins == null)
                return this.MissingPlugin;
            if (this.ValidFilterViewPlugins.Count < index + 1)
                return this.MissingPlugin;
            return this.ValidFilterViewPlugins[index];
        }

        #endregion
        #region InitializePluginsAsync

        public async Task InitializePluginsAsync()
        {
            if (this.ActiveServerItem == null)
                return;
            await this.ActiveServerItem.InitializePluginsAsync();
            if (this.ActiveServerItem.Plugins == null)
            {
                this.ValidEditViewPlugins = new List<Sidvall.IdentityManager.UI.Entities.Plugin>();
                this.ValidFilterPlugins = new List<Sidvall.IdentityManager.UI.Entities.Plugin>();
                this.ValidFilterViewPlugins = new List<Sidvall.IdentityManager.UI.Entities.Plugin>();
            }
            else
            {
                this.ValidEditViewPlugins = (from o in this.ActiveServerItem.Plugins
                                             where o.ShowEditView
                                             select o).ToList();
                this.ValidFilterPlugins = (from o in this.ActiveServerItem.Plugins
                                           where o.ProcessFilter
                                           select o).ToList();
                this.ValidFilterViewPlugins = (from o in this.ActiveServerItem.Plugins
                                               where o.ShowFilterView
                                               select o).ToList();
            }
        }

        #endregion

        #region LogOnAsync

        private async Task LogOnAsync(bool logOff)
        {
            if (string.IsNullOrWhiteSpace(Sidvall.IdentityManager.Security.SecurityManager.AuthorizeEndpoint))
                return;
            if ((logOff) || (!await Sidvall.SystemContext.Current.AuthenticationStrategyManager.NewAuthenticationHeaderFromRefreshTokenAsync()))
            {
                var response = await Sidvall.UI.SystemContext.Current.DialogManager.LogOnAsync(Sidvall.IdentityManager.Security.SecurityManager.AuthorizeEndpoint,
                    Sidvall.IdentityManager.Configuration.SettingsManager.STSClientIdResolved,
                    Sidvall.IdentityManager.Security.SecurityManager.ResponseType,
                    Sidvall.IdentityManager.Security.SecurityManager.Scope,
                    Sidvall.IdentityManager.Security.SecurityManager.ClientRedirectAddress,
                    Sidvall.IdentityManager.Configuration.SettingsManager.TwoFactorProviderResolved,
                    null,
                    Sidvall.IdentityManager.Security.SecurityManager.LogOffEndpoint,
                    null,
                    Sidvall.IdentityManager.Security.SecurityManager.AuthorityTokenEndpoint,
                    Sidvall.IdentityManager.Configuration.SettingsManager.STSClientSecretResolved);
                if (response?.TokenResponse != null)
                {
                }
                else
                {
                    throw new Sidvall.Security.UnauthorizedException();
                }
            }
        }

        #endregion

        #region LoadServerInfoAsync

        public async Task<Sidvall.IdentityManager.UI.Entities.UserConfiguration> LoadServerInfoAsync(bool logOn, bool logOff)
        {
            try
            {
                this.UserConfiguration.ClearCustomFields();
                Sidvall.IdentityManager.SystemContext.Current.ServerContent = null;
                Sidvall.SystemContext.Current.PrincipalManager.InitializeCurrentPrincipal("local", null);
                if (logOn)
                    await LogOnAsync(logOff);
                await Sidvall.IdentityManager.SystemContext.Current.LoadServerContentAsync(true);
                Sidvall.SystemContext.Current.PrincipalManager.InitializeCurrentPrincipal("local", Sidvall.IdentityManager.SystemContext.Current.ServerContent.UserItem.Claims);
                this.ActiveServerItem.IsLoadedServer = true;
                this.ActiveServerItem.StatusMessageServer = "OK";
            }
            catch (System.Exception ex)
            {
                this.ActiveServerItem.StatusMessageServer = Sidvall.SystemContext.Current.SystemExceptionManager.GetMessage(ex);
            }

            // Notify change
            var message = new ServerManagerMessage(this);
            Sidvall.UI.EventManager.Publish(message);

            return this.UserConfiguration;
        }

        #endregion
        #region LoadUserConfiguration

        public Sidvall.IdentityManager.UI.Entities.UserConfiguration LoadUserConfiguration(string content)
        {
            Sidvall.IdentityManager.Net.SimpleServices.V1.UserConfiguration dataItem;
            Sidvall.IdentityManager.UI.Entities.UserConfiguration item;

            dataItem = Sidvall.IdentityManager.SystemContext.Current.LoadUserConfiguration(content);
            item = GetItem(dataItem, null);
            this.UserConfiguration = item;

            return this.UserConfiguration;
        }

        #endregion
        #region LoadUserConfigurationAsync

        public async Task<Sidvall.IdentityManager.UI.Entities.UserConfiguration> LoadUserConfigurationAsync()
        {
            Sidvall.IdentityManager.Net.SimpleServices.V1.UserConfiguration dataItem;
            Sidvall.IdentityManager.UI.Entities.UserConfiguration item;

            dataItem = await Sidvall.IdentityManager.SystemContext.Current.LoadUserConfigurationAsync();
            item = GetItem(dataItem, this.UserConfiguration);
            this.UserConfiguration = item;

            return this.UserConfiguration;
        }

        #endregion
        #region SaveUserConfigurationAsync

        public async Task<Sidvall.IdentityManager.UI.Entities.UserConfiguration> SaveUserConfigurationAsync(Sidvall.IdentityManager.UI.Entities.UserConfiguration configuration, bool updateConnections)
        {
            Sidvall.IdentityManager.Net.SimpleServices.V1.UserConfiguration dataItem;
            Sidvall.IdentityManager.UI.Entities.UserConfiguration item;

            dataItem = new Net.SimpleServices.V1.UserConfiguration();
            dataItem.Import(configuration, Sidvall.Data.CopySettings.FullCopyCurrent(Sidvall.Data.DataRowContextOption.None, null));
            dataItem = await Sidvall.IdentityManager.SystemContext.Current.SaveUserConfigurationAsync(dataItem);
            item = GetItem(dataItem, configuration);
            this.UserConfiguration = item;
            if (updateConnections)
            {
                await LoadServerInfoAsync(true, false);
            }
            await Sidvall.SystemContext.Current.TypeCache.AddAssembliesAsync(this.UserConfiguration.PluginPath);
            await InitializePluginsAsync();
            return this.UserConfiguration;
        }

        #endregion

        #endregion
        #region Private Members

        #region MissingPlugin

        private Sidvall.IdentityManager.UI.Entities.Plugin _MissingPlugin;
        private Sidvall.IdentityManager.UI.Entities.Plugin MissingPlugin
        {
            get
            {
                Sidvall.IdentityManager.UI.Entities.Plugin item;

                if (_MissingPlugin == null)
                {
                    item = new Sidvall.IdentityManager.UI.Entities.Plugin()
                    {
                    };
                    _MissingPlugin = item;
                }
                return _MissingPlugin;
            }
        }

        #endregion

        #region GetItem

        private static Sidvall.IdentityManager.UI.Entities.UserConfiguration GetItem(Sidvall.IdentityManager.Data.IUserConfiguration dataItem, Sidvall.IdentityManager.UI.Entities.UserConfiguration configuration)
        {
            Sidvall.IdentityManager.UI.Entities.UserConfiguration item;

            item = new Sidvall.IdentityManager.UI.Entities.UserConfiguration();
            item.Import(dataItem, Sidvall.Data.CopySettings.FullCopyAll(Sidvall.Data.DataRowContextOption.None, null));
            item.ImportCustomFields(configuration);
            item.AcceptChanges();

            return item;
        }

        #endregion

        #endregion
    }
}